import SparkMD5 from 'park-md5'; // 获取文件的Md5值

const uploadQueue = []; // 任务队列
const chunkStatus = new Map(); // 记录文件的上传状态和重试次数
const activeTask = 3; // 最大并发控制

uploadFile();
// 上传文件
const uploadFile = () => {
    // 判断文件类型...

    // 限制文件大小...

    // 开始上传
    handleUpload();
}

// 处理上传
const handleUpload = async (file) => {
    // 生成文件切片
    const chunks = getFileChunks(file);
    // 计算MD5
    const fileMd5 = await calculateFileMD5(file);

    // 判断文件是否已存在于服务端
    const { data: checkData } = await api1({}); // 服务端接口
    // 文件已存在，秒传
    if (checkData.state === 1) {
        // 更新文件上传状态和进度100%
        return;
    }
    // 第一次上传，分片上传
    chunkStatus = new Map();
    chunks.forEach((_, index) => {
        chunkStatus.set(index, { status: 'pending', retryCount: 0 })
    });

    // 创建上传任务
    const uploadTasks = chunks.map((chunk, index) => ({
        chunk,
        index,
        fileMd5,
        fileName: file.name
    }));

    uploadQueue = uploadTasks;

    await hanleUploadQueue();
}

// 获取文件切片集合
const getFileChunks = (file) => {
    const chunkSize = 2 * 1024 * 1024; // 切片大小2M
    const chunks = [];
    let cur = 0;
    while (cur < file.size) {
        chunks.push(file.slice(cur, cur + chunkSize));
        cur += chunkSize
    }
    return chunks;
}
// 获取文件的md5值
const calculateFileMD5 = (file) => {
    return new Promise((resolve, reject) => {
        // 创建文件阅读器
        const reader = new FileReader(); 
        // 读取文件
        reader.readAsArrayBuffer(file);
        reader.onload = (e) => {
            const buffer = e.target.result;
            // 创建sparkMd5示例
            const spark = new SparkMD5.ArrayBuffer();
            spark.append(buffer);
            const md5 = spark.end();
            resolve(md5);
        }
        reader.onerror = (e) => {
            reject(e);
        }
    })
}
// 文件上传
const hanleUploadQueue = () => {
    while (uploadQueue.length > 0 && activeTask < 3) {
        const task = uploadQueue.shift();
        uploadChunk(task);
        activeTask++;
    }
}

// 上传切片
const uploadChunk = async (task) => {
    const { chunk, index, fileMd5, fileName } = task;

    try {
        const formData = new FileData();
        formData.append('file', chunk);
        formData.append('chunkIndex', index);
        formData.append('md5', fileMd5);
        formData.append('fileName', fileName);

        const { data } = await ({
            method: 'post',
            url: '',
            data: formData,
            headers: {
                'Content-Type': 'multipart/form-data'
            },
            onUploadProgress: (e) => {
                const progress = Math.round((e.loaded / e.total) * 100);
                console.log(`上传进度：${progress}%`);
            }
        })
        // 更新当前切片的状态
        const chunkInfo = chunkStatus.get(index);
        chunkStatus.set(index, { status: 'success', retryCount: chunkInfo.retryCount });

        // 检查是否所有切片上传成功
        const allChunks = Array.from(chunkStatus.values());
        const allSuccess = allChunks.every(c => c.status === 'success');
        if (allSuccess) {
            // 所有切片上传成功，更新整体的成功状态和进度
            return;
        }
    } catch (error) {
        // 上传失败，更新状态和重试次数，重新上传
    } finally {
        activeTask--;
        // 继续执行切片上传任务
        handleUploadQueue();
    }
}